﻿using LJ.EventBus.Data;
using LJ.EventBus.HornedSerpent.Transport.Abstractions;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LJ.EventBus.HornedSerpent.Transport.InMemoryQueue.Internal;

public class MemoryQueue : IMemoryQueue
{
    private static readonly object Lock = new();
    public Dictionary<string, List<string>> TopicGroups = [];
    public Dictionary<string, IInMemoryQueueConsumerClient> InMemoryQueueConsumerClients = [];


    public void RegisterConsumerClient(string groupId, IInMemoryQueueConsumerClient inMemoryQueueConsumerClient)
    {
        lock (Lock)
        {
            InMemoryQueueConsumerClients[groupId] = inMemoryQueueConsumerClient;
        }
    }

   

    public void Subscribe(string groupId, IEnumerable<string> topics)
    {
        lock (Lock)
        {
            foreach (var topic in topics)
            {
                if (TopicGroups.TryGetValue(topic, out var value))
                {
                    if (!value.Contains(groupId))
                    {
                        value.Add(groupId);
                    }
                }
                else
                {
                    TopicGroups.Add(topic, [groupId]);
                }
            }
        }
    }

    public void Unsubscribe(string groupId)
    {
        InMemoryQueueConsumerClients.Remove(groupId);
    }

    public void Send(EventBusTransportData transportData)
    {
        var name = transportData.GetName();
        lock (Lock)
        {
            if (TopicGroups.TryGetValue(name, out var groupList))
            {
                foreach (var groupId in groupList)
                {
                    
                    if (InMemoryQueueConsumerClients.TryGetValue(groupId, out var consumerClient))
                    {
                        var transportDataCopy =
                            new EventBusTransportData(transportData.Headers.ToDictionary(o => o.Key, o => o.Value),
                                transportData.Body)
                            {
                                Headers =
                                {
                                   [EventBusHeaders.Group] = groupId
                                }
                            };

                        consumerClient.AddSubscribeData(transportDataCopy);
                    }
                }
            }
            else
            {
                throw new InvalidOperationException(
                    $"Cannot find the corresponding group for {name}. Have you subscribed?");
            }
        }
    }
}